/**
 * 
 */
package stc.skymobi.content.transformer;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import stc.skymobi.content.Bean2PathTransformer;


/**
 * @author hp
 *
 */
public abstract class ExcelBean2PathTransformer implements Bean2PathTransformer {

    private static final Logger logger 
		= LoggerFactory.getLogger(ExcelBean2PathTransformer.class);
    
    private	AtomicReference<Bean2PathTransformer> proxy =
    	new AtomicReference<Bean2PathTransformer>();
    
    public  List<String> propertyNames = new ArrayList<String>();
    public  String      pathName  = "";
    public  String      sheetName;
    
    protected abstract InputStream createInputStream();
    
    /**
     * @param sheetName the sheetName to set
     */
    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }

    private int findColumnBy(HSSFRow row, String title) {
        int minColIx = row.getFirstCellNum();
        int maxColIx = row.getLastCellNum();
        for(int colIx=minColIx; colIx < maxColIx; colIx++) {
          HSSFCell cell = row.getCell(colIx);
          if(cell == null) {
            continue;
          }
          if (cell.toString().equals(title)) {
              return colIx;
          }
        }
        return -1;
    }

    public void load() throws IOException {
        POIFSFileSystem fs = new POIFSFileSystem(createInputStream());
        
        HSSFWorkbook wb = new HSSFWorkbook(fs);
        HSSFSheet sheet = wb.getSheet(sheetName);
        
        DefaultBean2PathTransformer dto2path = new DefaultBean2PathTransformer();
        dto2path.setPropertyNames(propertyNames);
        dto2path.clearTable();
        
        int[] idxs = new int[propertyNames.size()];
        
        HSSFRow firstRow = sheet.getRow(0);
        for ( int i = 0; i < idxs.length; i++) {
            idxs[i] = findColumnBy(firstRow, propertyNames.get(i));
        }
        
        int pathIdx = findColumnBy(firstRow, pathName);
        
        for ( int rowIdx = 1; rowIdx <= sheet.getLastRowNum(); rowIdx ++ ) {
            HSSFRow row = sheet.getRow(rowIdx);
            String  key = "";
            String  split = "";
            for ( int i = 0; i < idxs.length; i++) {
            	HSSFCell cell = row.getCell(idxs[i]);
            	String	cellValue;
            	if ( HSSFCell.CELL_TYPE_NUMERIC == cell.getCellType() ) {
            		cellValue = Integer.toString( (int)(cell.getNumericCellValue()) );
            	}
            	else {
            		cellValue = cell.toString();
            	}
            		
                key += split + cellValue;
                split = ":";
            }
            String path = row.getCell(pathIdx).toString();
         
            dto2path.addRow(key, path);
            if ( logger.isDebugEnabled() ) {
            	logger.debug("load: [" + rowIdx + "] key is '" + key + "', and path is [" + path + "]");
            }
        }
        proxy.set(dto2path);
    }

    /**
     * @param propertyNames the propertyNames to set
     */
    public void setPropertyNames(List<String> propertyNames) {
        this.propertyNames.clear();
        this.propertyNames.addAll(propertyNames);
    }

    /**
     * @param pathName the pathName to set
     */
    public void setPathName(String pathName) {
        this.pathName = pathName;
    }

    /* (non-Javadoc)
     * @see com.skymobi.util.Transformer#transform(java.lang.Object)
     */
    public String transform(Object from) {
    	Bean2PathTransformer bean2path = proxy.get();
    	if ( null != bean2path ) {
    		return bean2path.transform(from);
    	}
        return null;
    }

	public List<String> getPropertyNames() {
		return Collections.unmodifiableList( propertyNames );
	}

	public String getPathName() {
		return pathName;
	}

	public String getSheetName() {
		return sheetName;
	}

}
